import datetime
import binascii

DATA_TYPES = {
    "实时数据": {"cn": "2011", "suffix": "Rtd"},
    "分钟数据": {"cn": "2051", "suffix": "Avg"},
    "小时数据": {"cn": "2061", "suffix": "Avg"},
    "日数据": {"cn": "2031", "suffix": "Avg"}
}


def calculate_crc16(data):
    """计算HJ212-2017标准的CRC16校验码"""
    if isinstance(data, bytes):
        text = data.decode('utf-8')
    else:
        text = data
    crc_hex = crcFast(text)
    return int(crc_hex, 16)


def crcFast(text):
    """HJ212-2017 CRC16校验算法"""
    data = bytearray(text, encoding='utf-8')
    crc = 0xffff
    dxs = 0xa001
    for i in range(len(data)):
        hibyte = crc >> 8
        crc = hibyte ^ data[i]
        for j in range(8):
            sbit = crc & 0x0001
            crc = crc >> 1
            if sbit == 1:
                crc ^= dxs
    return str(hex(crc)[2:]).zfill(4)


def generate_hj212_message(mn, factor_data, data_type="实时数据", st="32", flag="0", data_time=None):
    """
    生成HJ212报文

    参数:
    mn (str): 设备唯一标识MN
    factor_data (dict): 因子数据，格式为 {'e01202': {'value': 10.5, 'flag': 'N'}, ...}
    data_type (str): 数据类型，可选: 实时数据/分钟数据/小时数据/日数据
    st (str): 系统编码，默认为32(环保数据)
    flag (str): 标志位，默认为0(正常)
    data_time (str): 自定义数据时间，格式为YYYYMMDDHHMMSS，如果为None则使用当前时间
    """
    # 获取数据类型配置
    type_config = DATA_TYPES.get(data_type, DATA_TYPES["实时数据"])
    cn = type_config["cn"]
    suffix = type_config["suffix"]

    # 生成时间
    if data_time is None:
        current_time = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
    else:
        current_time = data_time

    # 生成CP数据段
    cp_items = [
        f"QN={current_time}",
        f"ST={st}",
        f"CN={cn}",
        "PW=123456",
        f"MN={mn}",
        f"Flag={flag}"
    ]

    # 生成数据段
    data_items = [f"DataTime={current_time}"]

    # 添加因子数据
    for factor, values in factor_data.items():
        value = values.get("value", "")
        item_flag = values.get("flag", "N")
        data_items.append(f"{factor}-{suffix}={value}")
        data_items.append(f"{factor}-Flag={item_flag}")

    # 组合数据段
    data_str = ";".join(data_items)
    cp_items.append(f"CP=&&{data_str}&&")
    cp_str = ";".join(cp_items)

    # 计算CRC校验
    qn_start = cp_str.find("QN=")
    cp_end = cp_str.rfind("&&") + 2
    crc_data = cp_str[qn_start:cp_end] if qn_start >= 0 and cp_end > 0 else cp_str
    crc_hex = crcFast(crc_data).upper()

    # 组合完整报文
    data_len = len(cp_str + crc_hex)
    full_message = f"##{str(data_len).zfill(4)}{cp_str}{crc_hex}\r\n"

    return full_message


def parse_hj212_response(response):
    """解析HJ212响应报文"""
    try:
        if not response.startswith("##") or not response.endswith("\r\n"):
            return {"error": "报文格式错误"}

        data_len = int(response[2:6])
        cp_str = response[6:-6]
        crc_hex = response[-6:-2]

        if crcFast(cp_str).upper() != crc_hex:
            return {"error": "CRC校验失败"}

        return {
            k: v for item in cp_str.split(";")
            if "=" in item for k, v in [item.split("=", 1)]
        }
    except Exception as e:
        return {"error": f"解析错误: {str(e)}"}